package com.douguo.recipe.network;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.exchange.Controller.ReportThread;
import com.exchange.Model.AdvertiserConfig;
import com.exchange.View.ResourceManager.IdMapper;
import com.exchange.View.ResourceManager.LayoutMapper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class DownloadPackage {
	private Context mContext;
	private int STEP = 50;
	private String root;
	private String fileName;
	private String url;
	private Notification notification;
	private NotificationManager notificationManager;
	private int notificationIcon;
	private String BREAK_NETWORK_CN = "请确定设备成功联接网络";
	private String BREAK_NETWORK_EN = "Please make sure you are connected to internet, update failed";

	private boolean SUCCEED = true;

	private boolean internalStorageAllowed = true;

	public static boolean isDownloading = false;
	
	private ERRORTYPE errorType = ERRORTYPE.None;

	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			try {
				Intent intent = new Intent("android.intent.action.VIEW");
				intent.setDataAndType(
						Uri.parse("file://" + DownloadPackage.this.root + "/"
								+ DownloadPackage.this.fileName),
						"application/vnd.android.package-archive");
				DownloadPackage.this.mContext.startActivity(intent);

			} catch (Exception e) {
				Log.e("can not install", e.getMessage());
				DownloadPackage.this.SUCCEED = false;
			}
		}
	};

	public boolean isDownloadSuccedd() {
		return this.SUCCEED;
	}

	public void setTickerText(String tickerText) {
		this.notification.contentView.setTextViewText(IdMapper.title(),
				tickerText);
	}

	public void setRoot(String root) {
		this.root = root;
	}

	public void setNotificationIcon(int icon) {
		this.notificationIcon = icon;
		this.notification.icon = icon;
		this.notification.contentView.setImageViewResource(IdMapper.appIcon(),
				icon);
	}

	public void allowInternalStorage(boolean allow) {
		this.internalStorageAllowed = allow;
	}

	public DownloadPackage(Context context, String url,
			String title, String name) {
		if (isDownloading) {
			Toast.makeText(context, "还有下载未完成，请稍候再试", 2000).show();
			return;
		}

		isDownloading = true;

		try {
			init(context, url, "开始下载应用：" + name , title, "正在下载" + name );
		} catch (Exception e) {
			Log.e("initialization error", e.getMessage());
			this.SUCCEED = false;
		}

		Toast.makeText(context, "开始下载应用：" + name, 2000).show();

		downloadFile();
	}

	public void downloadFile() {
		if (!(this.SUCCEED)) {
			return;
		}
		checkRoot(this.root);

		Thread thread = new Thread() {
			public void run() {
				if (DownloadPackage.this.errorType == DownloadPackage.ERRORTYPE.SdcardError) {
					if (DownloadPackage.this.internalStorageAllowed) {
						DownloadPackage.this.saveToMemory();
					}

				} else {
					DownloadPackage.this.saveToSdCard();
				}
				DownloadPackage.isDownloading = false;
			}
		};
		thread.start();
	}

	private void init(Context context, String url, String tickerText,
			String title, String description) {
		this.mContext = context;
		checkEnviroment();
		if (this.errorType == ERRORTYPE.EnviromentError) {
			this.SUCCEED = false;
			return;
		}

		File sdcardDir = Environment.getExternalStorageDirectory();
		this.root = sdcardDir.getParent() + "/" + sdcardDir.getName()
				+ "/download";

		this.url = url;
		this.notificationIcon = 17301633;

		this.notification = new Notification(this.notificationIcon, tickerText,
				1L);
		this.notification.flags |= 2;

		RemoteViews expandedView = new RemoteViews(
				this.mContext.getPackageName(),
				LayoutMapper.exchange_download_notification());
		expandedView.setProgressBar(IdMapper.progress_bar(), 100, 0, false);
		expandedView.setTextViewText(IdMapper.progress_text(), "0%");
		expandedView.setTextViewText(IdMapper.title(), title);
		expandedView.setTextViewText(IdMapper.description(), description);
		expandedView.setImageViewResource(IdMapper.appIcon(),
				this.notificationIcon);
		this.notification.contentView = expandedView;

		Intent intent = new Intent();
		intent.setClassName(this.mContext.getPackageName(), this.mContext
				.getClass().getName());
		this.notification.contentIntent = PendingIntent.getActivity(
				this.mContext, 0, intent, 134217728);
		this.notificationManager = ((NotificationManager) this.mContext
				.getSystemService("notification"));
	}

	private void saveToSdCard() {
		try {
			byte[] bytes = readDataToMemory(this.url);
			if (!(this.SUCCEED)) {
				this.notificationManager.cancel(0);
				return;
			}
			this.fileName = String.valueOf(System.currentTimeMillis() + ".apk");
			FileOutputStream fileOutputStream = new FileOutputStream(new File(
					this.root, this.fileName));
			fileOutputStream.write(bytes, 0, bytes.length);
			fileOutputStream.close();
			this.notificationManager.cancel(0);
			this.mHandler.sendEmptyMessage(0);
		} catch (Exception e) {
			Log.e("cannot save to sd card", e.getStackTrace().toString());
			this.SUCCEED = false;
		}
	}

	private void saveToMemory() {
		try {
			this.fileName = String.valueOf(System.currentTimeMillis() + ".apk");
			byte[] content = readDataToMemory(this.url);
			if (!(this.SUCCEED)) {
				this.notificationManager.cancel(0);
				return;
			}

			this.root = this.mContext.getFilesDir().getAbsolutePath();

			FileOutputStream fos = this.mContext.openFileOutput(this.fileName,
					3);
			fos.write(content);
			fos.close();

			this.notificationManager.cancel(0);
			this.mHandler.sendEmptyMessage(0);
		} catch (Exception e) {
			Log.e("can not save to memory", e.getMessage());
			this.SUCCEED = false;
		}
	}

	private byte[] readDataToMemory(String fileName) throws Exception {
		URL u = new URL(this.url);
		HttpURLConnection conn = (HttpURLConnection) u.openConnection();
		conn.setRequestMethod("GET");
		conn.setDoOutput(true);
		conn.setConnectTimeout(5000);
		conn.connect();

		InputStream inputStream = conn.getInputStream();
		this.notificationManager.notify(0, this.notification);

		byte[] buffer = new byte[1024];
		int cycle = 0;
		int len = 0;
		int accLen = 0;
		int totalLength = conn.getContentLength();

		byte[] bytes = new byte[totalLength];
		int counter = 0;
		while ((len = inputStream.read(buffer)) > 0) {
			accLen += len;
			for (int i = 0; i < len; ++i) {
				bytes[(counter++)] = buffer[i];
			}

			if (cycle++ % this.STEP != 0)
				continue;
			if (!(isOnline())) {
				this.SUCCEED = false;
				break;
			}
			int progress = (int) (accLen * 100.0F / totalLength);
			this.notification.contentView.setProgressBar(
					IdMapper.progress_bar(), 100, progress, false);
			this.notification.contentView.setTextViewText(
					IdMapper.progress_text(), String.valueOf(progress) + "%");
			this.notificationManager.notify(0, this.notification);
		}

		inputStream.close();

		return bytes;
	}

	private void checkEnviroment() {
		if (!(isOnline())) {
			Toast.makeText(this.mContext, getLocaleNetworkBreak(), 3).show();
			this.errorType = ERRORTYPE.EnviromentError;
			return;
		}
		if (!(isSdCardWrittenable())) {
			this.errorType = ERRORTYPE.SdcardError;
			return;
		}
		this.errorType = ERRORTYPE.None;
	}

	private void checkRoot(String root) {
		File path = new File(root);
		if (!(path.exists()))
			path.mkdirs();
	}

	private boolean isOnline() {
		try {
			ConnectivityManager cm = (ConnectivityManager) this.mContext
					.getSystemService("connectivity");
			NetworkInfo ni = cm.getActiveNetworkInfo();
			if (ni != null) {
				return ni.isConnectedOrConnecting();
			}
			return false;
		} catch (Exception e) {
		}
		return true;
	}

	private boolean isSdCardWrittenable() {
		return (Environment.getExternalStorageState().equals("mounted"));
	}

	private String getLocaleNetworkBreak() {
		Locale locale = this.mContext.getResources().getConfiguration().locale;

		if (locale.toString().equals("zh_CN")) {
			return this.BREAK_NETWORK_CN;
		}
		return this.BREAK_NETWORK_EN;
	}

	private static enum ERRORTYPE {
		None, EnviromentError, SdcardError;
	}
}
